package com.roger.springcloudGreenwich.controller;

import com.roger.springcloudGreenwich.component.RedisRaterLimiter;
import com.roger.springcloudGreenwich.component.StrUtil;
import com.roger.springcloudGreenwich.entity.Student;
import com.roger.springcloudGreenwich.lock.RedissonManager;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * Created by admin on 2020/4/10.
 */
@RestController
@Slf4j
public class TestRedisController {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisRaterLimiter redisRaterLimiter;

    @GetMapping("/test")
    public Object test(){
        String token = redisRaterLimiter.acquireToken("upload", 1L, 1000L * 300L);
        if (StrUtil.isBlank(token)) {//没有拿到令牌
            return "上传那么多干嘛，等等再传吧";
        }

        Student student = new Student();
        student.setId(1L);
        student.setName("roger");
        student.setAge(20);
        redisTemplate.opsForValue().set("TEST-REDIS:STUDENT",student);
        Object obj = redisTemplate.opsForValue().get("TEST-REDIS:STUDENT");
        redisTemplate.expire("TEST-REDIS:STUDENT" , 1000 * 30, TimeUnit.MILLISECONDS);

        return obj;
    }

    /** 释放锁lua脚本 */
    private static final String RELEASE_LOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

    @GetMapping("/testLua")
    public Object testLua(){
        String lockKey = "123";
        String UUID = java.util.UUID.randomUUID().toString();
        boolean success = stringRedisTemplate.opsForValue().setIfAbsent(lockKey,UUID,3, TimeUnit.SECONDS);
        if (!success){
            System.out.println("锁已存在");
            return "锁已存在";
        }
        // 指定 lua 脚本，并且指定返回值类型
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA_SCRIPT,Long.class);
        // 参数一：redisScript，参数二：key列表，参数三：arg（可多个）
        Long result = stringRedisTemplate.execute(redisScript, Collections.singletonList(lockKey),UUID);
        System.out.println(result);
        return result;
    }

    @GetMapping("/redis")
    public String getKey(){
        ValueOperations valueOperations = stringRedisTemplate.opsForValue();
        Long i = 0L;
        boolean flag = stringRedisTemplate.opsForValue().setIfAbsent("visitCount_redis","1",10,TimeUnit.SECONDS);
        if(flag){
            System.out.println("第一次访问");
        }else{
            valueOperations.increment("visitCount_redis");
        }
        i = Long.valueOf(valueOperations.get("visitCount_redis").toString());

        if(i>10){
            return "此接口十秒内访问超过10次，请稍后访问";
        }

        return valueOperations.get("visitCount_redis").toString();
    }



    @GetMapping("/lock/{id}")
    public Object lock(@PathVariable int id) throws Exception{
        RedissonClient redissonClient = RedissonManager.getRedisson();

        RLock lock1 = redissonClient.getLock("lock1");
        //System.out.println(lock1.isLocked());
        try {
            boolean isLocked = lock1.tryLock(3, TimeUnit.SECONDS);//获得到了锁
            if(isLocked){
                System.out.println(id + " i am working");
                Thread.sleep(1000 * 30);
                System.out.println(id + "work finished");
                lock1.unlock();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock1.unlock();
        }
        return id + "success";
    }

    @GetMapping(value = "getSession")
    public Object getSession(HttpServletRequest request){
        HttpSession session = request.getSession(true);
        log.info("session id==={}", session.getId());
        return session.getAttribute("foo");
    }

    @GetMapping(value = "setSession")
    public Object setSession(HttpServletRequest request){
        HttpSession session = request.getSession(true);
        log.info("session id==={}", session.getId());
        session.setAttribute("user" , "tome");
        return "success";
    }

}
